//
// Created by DELL on 2021/3/12.
//

#ifndef SYLAR_TIMER_H
#define SYLAR_TIMER_H

#include <memory>
#include "mutex.h"
#include <set>
#include <vector>

namespace sylar {
    class TimerManager;

    class Timer : public std::enable_shared_from_this<Timer> {
        friend class TimerManager;

    public:
        using ptr = std::shared_ptr<Timer>;
        bool cancel();
        bool refresh();
        bool reset(uint64_t ms, bool from_now);
    private:
        Timer(uint64_t ms, std::function<void()> cb, bool recurring, TimerManager *manager);
        Timer(uint64_t next);

    private:
        // 循环定时器
        bool m_recurring = false;
        // 循环定时器执行周期
        uint64_t m_ms = 0;
        // 精确执行时间
        uint64_t m_next = 0;
        std::function<void()> m_cb;
        TimerManager *m_manager = nullptr;
    private:
        struct Comparator {
            bool operator()(const Timer::ptr &lhs, const Timer::ptr &rhs) const;
        };
    };

    class TimerManager {
        friend class Timer;

    public:
        using RWMutexType = RWMutex;

        TimerManager();

        virtual ~TimerManager();

        Timer::ptr addTimer(uint64_t ms, std::function<void()> cb, bool recurring = false);

        Timer::ptr
        addConditionTimer(uint64_t ms, std::function<void()> cb,
                          std::weak_ptr<void> weak_cond, bool recurring = false);

        uint64_t getNextTimer();

        void listExpiredTimCb(std::vector<std::function<void()>> &cbs);

    protected:
        virtual void onTimerInsertedAtFront() = 0;
        void addTimer(Timer::ptr val,RWMutexType::WriteLock&lock);
        bool hasTimer();
    private:
      bool  detectClockRollover(uint64_t now_ms);
    private:
        RWMutexType m_mutex;
        std::set<Timer::ptr, Timer::Comparator> m_timers;
        /// 是否触发onTimerInsertedAtFront
        bool m_tickled = false;
        /// 上次执行时间
        uint64_t m_previouseTime = 0;
    };
}
#endif //SYLAR_TIMER_H
